package com.fly.core.config.spring;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.FilterType;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Controller;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;

import com.fly.core.config.SwaggerConfig;

/**
 * 
 * 取代spring-mvc.xml
 * 
 * @author 00fly
 * @version [版本号, 2021年3月27日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@Configuration
@EnableWebMvc
@EnableAspectJAutoProxy
@ComponentScan(basePackages = {"com.fly.demo.controller", "com.fly.core.config"}, useDefaultFilters = false, includeFilters = {
    @ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Controller.class, RestController.class, ControllerAdvice.class}), @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = SwaggerConfig.class)})
public class SpringMvcConfiguration extends WebMvcConfigurerAdapter
{
    /**
     * 打开 JSR 303
     */
    @Bean
    public LocalValidatorFactoryBean validator()
    {
        return new LocalValidatorFactoryBean();
    }
    
    /**
     * 处理静态文件
     * 
     * @param configurer
     */
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer)
    {
        configurer.enable();
    }
    
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters)
    {
        converters.add(this.stringHttpMessageConverter());
        converters.add(this.mappingJackson2HttpMessageConverter());
    }
    
    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer)
    {
        configurer.defaultContentType(MediaType.TEXT_HTML);
        configurer.ignoreUnknownPathExtensions(false);
        configurer.favorPathExtension(true);
        configurer.favorParameter(false);
        Map<String, MediaType> mediaTypes = new HashMap<>();
        mediaTypes.put("atom", MediaType.APPLICATION_ATOM_XML);
        mediaTypes.put("json", MediaType.APPLICATION_JSON);
        mediaTypes.put("html", MediaType.TEXT_HTML);
        configurer.mediaTypes(mediaTypes);
    }
    
    @Bean
    public StringHttpMessageConverter stringHttpMessageConverter()
    {
        StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
        return stringHttpMessageConverter;
    }
    
    @Bean
    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter()
    {
        MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
        List<MediaType> list = new ArrayList<>();
        list.add(MediaType.APPLICATION_JSON);
        list.add(MediaType.APPLICATION_XML);
        list.add(MediaType.TEXT_PLAIN);
        list.add(MediaType.TEXT_HTML);
        list.add(MediaType.TEXT_XML);
        messageConverter.setSupportedMediaTypes(list);
        return messageConverter;
    }
    
    @Bean
    public FreeMarkerConfigurer freeMarkerConfigurer()
    {
        FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
        configurer.setTemplateLoaderPath("/templates/");
        configurer.setDefaultEncoding(StandardCharsets.UTF_8.name());
        
        Properties settings = new Properties();
        settings.setProperty("template_update_delay", "5");
        settings.setProperty("default_encoding", StandardCharsets.UTF_8.name());
        settings.setProperty("locale", StandardCharsets.UTF_8.name());
        settings.setProperty("datetime_format", "yyyy-MM-dd HH:mm:ss");
        settings.setProperty("time_format", "HH:mm:ss");
        settings.setProperty("number_format", "0.####");
        settings.setProperty("boolean_format", "true,false");
        settings.setProperty("whitespace_stripping", "true");
        settings.setProperty("tag_syntax", "auto_detect");
        settings.setProperty("url_escaping_charset", StandardCharsets.UTF_8.name());
        configurer.setFreemarkerSettings(settings);
        return configurer;
    }
    
    @Bean
    public ViewResolver freeMarkerViewResolver()
    {
        FreeMarkerViewResolver viewResolver = new FreeMarkerViewResolver();
        viewResolver.setCache(true);
        viewResolver.setPrefix("");
        viewResolver.setSuffix(".html");
        viewResolver.setContentType("text/html;charset=UTF-8");
        viewResolver.setExposeSpringMacroHelpers(true);
        viewResolver.setExposeRequestAttributes(false);
        viewResolver.setExposeSessionAttributes(false);
        return viewResolver;
    }
    
    // /**
    // * 加载静态资源文件
    // */
    // @Override
    // public void addResourceHandlers(final ResourceHandlerRegistry registry)
    // {
    // registry.addResourceHandler("/images/**").addResourceLocations("/images/");
    // registry.addResourceHandler("/css/**").addResourceLocations("/css/");
    // registry.addResourceHandler("/js/**").addResourceLocations("/js/");
    // }
    
}
